import 'dart:io';
import 'dart:math';

import 'package:flutter/cupertino.dart';

import 'bean/MusicBean.dart';
import 'lib_music_platform_interface.dart';
import 'listener/OnFftDataListener.dart';
import 'listener/OnMusicCallback.dart';

class LibMusic extends ChangeNotifier implements OnMusicCallback, OnFftDataListener {
  //单例
  static LibMusic? _instance;

  static LibMusic get instance => _instance ??= LibMusic._();

  //音乐列表数据
  List<MusicBean> playList = [];

  int currentIndex = 0;

  List<OnMusicCallback> _onMusicCallbackList = [];
  List<OnFftDataListener> _onFftDataListenerList = [];

  void addOnMusicCallback(OnMusicCallback callback) {
    if (!_onMusicCallbackList.contains(callback)) {
      _onMusicCallbackList.add(callback);
    }
  }

  void removeOnMusicCallback(OnMusicCallback callback) {
    _onMusicCallbackList.remove(callback);
  }

  void addOnFftDataListener(OnFftDataListener listener) {
    if (!_onFftDataListenerList.contains(listener)) {
      _onFftDataListenerList.add(listener);
    }
  }

  void removeOnFftDataListener(OnFftDataListener listener) {
    _onFftDataListenerList.remove(listener);
  }

  LibMusic._() {
    LibMusicPlatform.instance.setOnMusicCallback(this);
    LibMusicPlatform.instance.setOnFftDataListener(this);
  }

  ///播放进度
  int progress = 0;

  int get currentProgress {
    return progress;
  }

  //是否正在播放
  bool isPlaying = false;

  bool get isPlayingMusic {
    return isPlaying;
  }
  int lastTime = 0;

  ///循环模式 0:列表循环,1:单曲循环,2:随机播放
  int _cycleMode = 0;

  int get cycleMode {
    return _cycleMode;
  }

  set cycleMode(int value) {
    _cycleMode = value;
  }

  //音量
  double _volume = 100;

  double get volume {
    return _volume;
  }

  set volume(double value) {
    _volume = value;
    LibMusicPlatform.instance.invokeMethod("setVolume", {"volume": value.toInt()});
    notifyListeners();
  }

  //获取音乐列表
  Future<List<MusicBean>> getMusicList() async {
    if (playList.isEmpty) {
      if (Platform.isAndroid) {
        if (playList.isEmpty) {
          var data = await LibMusicPlatform.instance.invokeMethod("getMusicList");
          if (data != null) {
            //print("data:$data");
            for (var item in data) {
              MusicBean bean = MusicBean()
                ..title = item["title"]
                ..artist = item["artist"]
                ..url = item["url"]
                ..duration = item["duration"];

              ///排除小于3秒的音乐文件
              if (bean.duration < 3000) {
                continue;
              }

              if (bean.url != null && bean.url!.isNotEmpty) {
                playList.add(bean);
              }
            }
            return playList;
          }
        }
      } else {
        var data = await LibMusicPlatform.instance.invokeMethod("getMusicList");
        if (data != null) {
          //print("data:$data");
          for (var item in data) {
            MusicBean bean = MusicBean()
              ..title = item["title"]
              ..artist = item["artist"]
              ..url = item["url"]
              ..duration = item["duration"];
            if (bean.url != null && bean.url!.isNotEmpty) {
              playList.add(bean);
            }
          }
          return playList;
        }
        return [];
      }
    }
    return playList;
  }

  Future<String?> getPlatformVersion() {
    return LibMusicPlatform.instance.getPlatformVersion();
  }


  void seekTo(int progress) {
    if (Platform.isIOS) {
      if (progress > (getCurrentMusic()!.duration! - 1.5 * 1000)) {
        onPlayComplete();
        return;
      }
    }
    this.progress = progress;
    LibMusicPlatform.instance.invokeMethod("seekTo", {"progress": progress});
  }

  void continuePlay() {
    LibMusicPlatform.instance.invokeMethod("continuePlay");
  }

  void pausePlay() {
    LibMusicPlatform.instance.invokeMethod("pausePlay");
  }

  void stopPlay() {
    LibMusicPlatform.instance.invokeMethod("stopPlay");
    isPlaying = false;
    progress = 0;
    onStopPlay();
  }

  MusicBean? getCurrentMusic() {
    MusicBean? bean;
    if (playList.isNotEmpty) {
      bean = playList[currentIndex];
    }
    return bean;
  }

  void startPlay(MusicBean bean) {
    if (bean.url != null) {
      currentIndex = playList.indexOf(bean);
      LibMusicPlatform.instance.invokeMethod("startPlay", {"uri": bean.url!});
    }
  }

  ///下一首
  void nextPlay() {
    if (playList.isEmpty) {
      return;
    }
    if (Platform.isAndroid) {
      stopPlay();
    }
    currentIndex++;
    currentIndex = currentIndex % playList.length;
    var currentMusic = getCurrentMusic();
    if (currentMusic != null) {
      startPlay(currentMusic);
    }
    //notifyListener();
  }

  ///上一首
  void prePlay() {
    if (playList.isEmpty) {
      return;
    }

    if (Platform.isAndroid) {
      stopPlay();
    }

    currentIndex--;
    if (currentIndex < 0) {
      currentIndex = playList.length - 1;
    }
    var currentMusic = getCurrentMusic();
    if (currentMusic != null) {
      startPlay(currentMusic);
    }
    //notifyListener();
  }


  ///fft数据预处理
  List<int> readyData(List<int> fft,int ledHeight, int effects) {
    //fft = VisualizerUtil.getWaveFormData(fft);
    List<int> list = [];
    for (var i = 0; i < fft.length; i++) {
      var fft2 = fft[i].abs();
      fft2 = min(fft2, 127);
      fft2 = (fft2 / 127 * ledHeight).toInt();
      if (effects == 1) {
        fft2 = max(fft2, 1);
      } else {
        fft2 = max(fft2, 2);
      }

      list.add(fft2);
    }
    return list;
  }


  @override
  void onFftDataCapture(List<int> data) {
    if ((DateTime.now().millisecondsSinceEpoch - lastTime) > 100) {
      lastTime = DateTime.now().millisecondsSinceEpoch;
      for (var listener in _onFftDataListenerList) {
        listener.onFftDataCapture(data);
      }
    }
  }

  @override
  void onPausePlay() {
    isPlaying = false;
    notifyListeners();
    for (var listener in _onMusicCallbackList) {
      listener.onPausePlay();
    }
  }

  @override
  void onPlayComplete() {
    if (isPlaying) {
      isPlaying = false;
      progress = 0;
      notifyListeners();
      for (var listener in _onMusicCallbackList) {
        listener.onPlayComplete();
      }
      if (cycleMode == 0) {
        nextPlay();
      } else if (cycleMode == 1) {
        stopPlay();
        var currentMusic = getCurrentMusic();
        if (currentMusic != null) {
          startPlay(currentMusic);
        }
      } else {
        stopPlay();
        currentIndex = Random().nextInt(playList.length);
        var currentMusic = getCurrentMusic();
        if (currentMusic != null) {
          startPlay(currentMusic);
        }
      }

    }
  }

  @override
  void onProgress(int progress) {
    if (isPlaying) {
      this.progress = max(0, progress);
      if (Platform.isIOS) {
        if (progress > (getCurrentMusic()!.duration! - 1.5 * 1000)) {
          onPlayComplete();
        } else {
          for (var listener in _onMusicCallbackList) {
            listener.onProgress(progress);
          }
        }
      } else {
        for (var listener in _onMusicCallbackList) {
          listener.onProgress(progress);
        }
      }
    }
  }

  @override
  void onStartPlay() {
    isPlaying = true;
    notifyListeners();
    for (var listener in _onMusicCallbackList) {
      listener.onStartPlay();
    }
  }

  @override
  void onWaveFormDataCapture(List<int> data) {}

  @override
  void onStopPlay() {
      isPlaying = false;
      progress = 0;
      notifyListeners();
      for (var listener in _onMusicCallbackList) {
        listener.onStopPlay();
      }
  }
}
